package parameters;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Properties;

import utils.NetworkUtils;

/**
 * This is the UpdateServer parameters manager class. It provides getters and setters methods
 * for all server parameters.
 * 
 * @author Uros Krkic
 */
public class RlmServerParameters implements DefaultParameterValues {
	
	private static int serverPort;
	private static String serverIP;
	private static String multicastIP;
	private static int multicastPort;
	private static int maxDBConnections;
	private static String dbDriver;
	private static String dbUrl;
	private static String dbUser;
	private static String dbPassword;

	private static String networkInterfaceToConnect;
	private static String macAddress;
	
	private static boolean isLan;
	
	
	private static final String propertiesFileName = "RlmServerConfig.properties";
		
	private static final String propDir = System.getProperty("user.dir") + "/configs";
	
	private static final String propFileName = propDir + File.separator + propertiesFileName;

	
	private RlmServerParameters() { }
	
	
	/**
	 * This method creates "UpdateServerConfig.properties" that stores server parameters with
	 * default values.
	 * @author Uros Krkic
	 */
	public static void createDefaultParameters() {
		Properties properties = new Properties();
		
		properties.setProperty("SERVER_PORT", intToString(SERVER_PORT));
		properties.setProperty("SERVER_IP", SERVER_IP);
		properties.setProperty("MULTICAST_IP", MULTICAST_IP);
		properties.setProperty("MULTICAST_PORT", intToString(MULTICAST_PORT));
		properties.setProperty("MAX_DB_CONNECTIONS", intToString(MAX_DB_CONNECTIONS));
		properties.setProperty("DB_DRIVER", DB_DRIVER);
		properties.setProperty("DB_URL", DB_URL);
		properties.setProperty("DB_USER", DB_USER);
		properties.setProperty("DB_PASSWORD", DB_PASSWORD);
		properties.setProperty("IS_LAN", booleanToString(IS_LAN));
		
		properties.setProperty("networkInterfaceToConnect", NIC_AUTO_SELECT);
		properties.setProperty("macAddress", MAC_ADDRESS);
		
		File propDirFile = new File(propDir);
		if ( !propDirFile.exists() ) {
			propDirFile.mkdir();
		}
		
		File propertiesFile = new File(propFileName);
		
		try {
			propertiesFile.createNewFile();
			properties.store(new FileOutputStream(propertiesFile), "RlmServerConfig");
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	 * This method loads server parameters from external file - UpdateServerConfig.properties.
	 * @author Uros Krkic
	 */
	public static void loadParameters() {
		
		File propertiesFile = new File(propFileName);
		
		if ( !propertiesFile.exists() ) {
			createDefaultParameters();
		}
		
		Properties properties = new Properties();
		
		try {
			properties.load(new FileInputStream(propertiesFile));
			
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
			return;
		}
		catch (IOException e) {
			e.printStackTrace();
			return;
		}
		
		try {
			serverPort = Integer.parseInt( properties.getProperty("SERVER_PORT", intToString(SERVER_PORT)) );
		}
		catch (NumberFormatException nfe) {
			serverPort = SERVER_PORT;
		}

		serverIP = properties.getProperty("SERVER_IP", SERVER_IP);
		multicastIP = properties.getProperty("MULTICAST_IP", MULTICAST_IP);
		
		try {
			multicastPort = Integer.parseInt( properties.getProperty("MULTICAST_PORT", intToString(MULTICAST_PORT)) );
		}
		catch (NumberFormatException nfe) {
			multicastPort = MULTICAST_PORT;
		}
		
		try {
			maxDBConnections = Integer.parseInt( properties.getProperty("MAX_DB_CONNECTIONS", intToString(MAX_DB_CONNECTIONS)) );
		}
		catch (NumberFormatException nfe) {
			maxDBConnections = MAX_DB_CONNECTIONS;
		}
		
		dbDriver = properties.getProperty("DB_DRIVER", DB_DRIVER);
		dbUrl = properties.getProperty("DB_URL", DB_URL);
		dbUser = properties.getProperty("DB_USER", DB_USER);
		dbPassword = properties.getProperty("DB_PASSWORD", DB_PASSWORD);
		
		networkInterfaceToConnect = properties.getProperty("networkInterfaceToConnect", NIC_AUTO_SELECT);
		macAddress = properties.getProperty("macAddress", MAC_ADDRESS);
		
		isLan = Boolean.parseBoolean( properties.getProperty("IS_LAN", booleanToString(IS_LAN)) );
	}
	
	
	/**
	 * This method stores server parameters to external file - UpdateServerConfig.properties.
	 * @author Uros Krkic
	 */
	public static void storeParameters() {

		Properties properties = new Properties();
		
		properties.setProperty("SERVER_PORT", intToString(serverPort));
		properties.setProperty("SERVER_IP", serverIP);
		properties.setProperty("MULTICAST_IP", multicastIP);
		properties.setProperty("MULTICAST_PORT", intToString(multicastPort));
		properties.setProperty("MAX_DB_CONNECTIONS", intToString(maxDBConnections));
		properties.setProperty("DB_DRIVER", dbDriver);
		properties.setProperty("DB_URL", dbUrl);
		properties.setProperty("DB_USER", dbUser);
		properties.setProperty("DB_PASSWORD", dbPassword);
		
		properties.setProperty("networkInterfaceToConnect", networkInterfaceToConnect);
		properties.setProperty("macAddress", macAddress);
		
		properties.setProperty("IS_LAN", booleanToString(isLan));
		
		
		File propertiesFile = new File(propFileName);
		
		try {
			if ( !propertiesFile.exists() ) {
				propertiesFile.createNewFile();
			}
			
			properties.store(new FileOutputStream(propertiesFile), "RlmServerConfig");
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	private static String intToString(int value) {
		return Integer.toString(value);
	}
	
	private static String booleanToString(boolean value) {
		return Boolean.toString(value);
	}
	
	
	/**
	 * This method prints all server paramters to stdout.
	 * @author Uros Krkic
	 */
	public static void printParameters() {
		System.out.println("Server IP: " + serverIP);
		System.out.println("Server Port: " + serverPort);
		System.out.println("Server Multicast IP: " + multicastIP);
		System.out.println("Server Multicast Port: " + multicastPort);
		System.out.println("Max DB Conenctions: " + maxDBConnections);
		System.out.println("DB Driver: " + dbDriver);
		System.out.println("DB Url: " + dbUrl);
		System.out.println("DB User: " + dbUser);
		System.out.println("DB Password: " + dbPassword);
		System.out.println("IS_LAN: " + isLan);
	}
	
	
	// getters and setters


	public static int getServerPort() {
		return serverPort;
	}


	public static void setServerPort(int serverPort) {
		RlmServerParameters.serverPort = serverPort;
	}


	public static String getServerIP() {
		return serverIP;
	}


	public static void setServerIP(String serverIP) {
		RlmServerParameters.serverIP = serverIP;
	}


	public static String getMulticastIP() {
		return multicastIP;
	}


	public static void setMulticastIP(String multicastIP) {
		RlmServerParameters.multicastIP = multicastIP;
	}


	public static int getMulticastPort() {
		return multicastPort;
	}


	public static void setMulticastPort(int multicastPort) {
		RlmServerParameters.multicastPort = multicastPort;
	}


	public static int getMaxDBConnections() {
		return maxDBConnections;
	}


	public static void setMaxDBConnections(int maxDBConnections) {
		RlmServerParameters.maxDBConnections = maxDBConnections;
	}


	public static String getDbDriver() {
		return dbDriver;
	}


	public static void setDbDriver(String dbDriver) {
		RlmServerParameters.dbDriver = dbDriver;
	}


	public static String getDbUrl() {
		return dbUrl;
	}


	public static void setDbUrl(String dbUrl) {
		RlmServerParameters.dbUrl = dbUrl;
	}


	public static String getDbUser() {
		return dbUser;
	}


	public static void setDbUser(String dbUser) {
		RlmServerParameters.dbUser = dbUser;
	}


	public static String getDbPassword() {
		return dbPassword;
	}


	public static void setDbPassword(String dbPassword) {
		RlmServerParameters.dbPassword = dbPassword;
	}

	
	public static String getNetworkInterfaceToConnect() {
		return getNetworkInterfaceToConnect(false);
	}
	
	
	public static String getNetworkInterfaceToConnect(boolean flag) {
//		return networkInterfaceToConnect.equalsIgnoreCase("null") ? null : networkInterfaceToConnect;
		
		if ( networkInterfaceToConnect.equals("null") )
			return null;
		
		if (flag == true) {
			return networkInterfaceToConnect;
		}

		if ( networkInterfaceToConnect.equals(NIC_AUTO_SELECT) ) {
			InetAddress ia = NetworkUtils.getLocalAddress();
			
			if (ia == null)
				return null;
			
			return ia.getHostAddress();
		}
		
		return networkInterfaceToConnect;
	}


	public static void setNetworkInterfaceToConnect(String networkInterfaceToConnect) {
		RlmServerParameters.networkInterfaceToConnect = networkInterfaceToConnect;
	}
	
	public static boolean isNICAutoSelect() {
		return networkInterfaceToConnect.equals(NIC_AUTO_SELECT);
	}
	
	public static String getMACAddress() {
		return macAddress;
	}
	
	public static void setMACAddress(String macAddress) {
		RlmServerParameters.macAddress = macAddress;
	}


	public static boolean isLan() {
		return isLan;
	}


	public static void setLan(boolean isLan) {
		RlmServerParameters.isLan = isLan;
	}
}
